home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
PACKET
/
TFLINK10
/
TFLNKSRC
/
TFLINK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-14
|
7KB
|
233 lines
/*
*-----------------------------------------------------------------------
*
* TFLINK - program to make TFPCX TSR running a Baycom modem on a
* COM port appear as a serial (HOST mode) TNC on a second COM port.
*
* tflink.c - main module for the TFLINK program
*
* This program glues together a standard serial COM port and the
* TFPCX Baycom driver TNC and firmware emulator program. In this
* manner, a PC and Baycom modem can be used together to emulate a
* WA8DED host-mode TNC for other external programs, for example,
* TNT running on Linux.
*
*-----------------------------------------------------------------------
*/
/* standard inclusion file */
#define MAIN_MODULE 1
#include "tflink.h"
#include "ibmcom.h"
/* imported routines */
bool tfpcx_check();
u_int tfpcx_version();
bool tfpcx_request();
u_char tfpcx_readch();
void tfpcx_writech( u_char );
bool getopts( int, char** );
/* local definitions */
#define TFLINK_VERSION ((1 << 8) | 0)
#define TSR_MEMORY 0x600
#define PIC_INTERRUPT_MASK_PORT 0x21
/* interrupt numbers */
#define INT1C 0x1C
#define INT21 0x21
#define INT21_TSR 0x31
#define INT21_TERMINATE 0x4C
#define INT21_FREE_MEM 0x49
/* module-local variables */
static u_char i8259bit;
static void interrupt (*old_int_1c)( void );
/*-----------------------------------------------------------------------*/
/*
* print out the options as they are set up so that the defaults are
* visible and any overrides confirmed. -N switches this off. Note
* that this routine predicts the base address ibmcom will use.
*/
void printopts() {
const int uart_base[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
int i, width; /* loop counter, box width */
/* set box width to 43 chars */
width = 43;
/* create a pretty box */
printf( "%c", 0xda );
for ( i=0; i<width-2; i++ ) printf( "%c", 0xc4 );
printf( "%c\n", 0xbf );
printf( "%c TFLINK version %2d.%02d - G0FRD %c\n", 0xb3,
(u_int)(TFLINK_VERSION >> 8),
(u_int)(TFLINK_VERSION & 0xFF), 0xb3 );
printf( "%c TFPCX - interrupt 0x%02X %c\n",
0xb3, tfpcx_interrupt, 0xb3 );
printf( "%c COM%1d - base address 0x%04X, %5d baud %c\n",
0xb3, sio_port, uart_base[sio_port-1], sio_baud, 0xb3 );
printf( "%c", 0xc0 );
for ( i=0; i<width-2; i++ ) printf( "%c", 0xc4 );
printf( "%c\n", 0xd9 );
}
/*-----------------------------------------------------------------------*/
/*
* timer interrupt handler - polls TFPCX for outgoing characters
*/
void interrupt int_1c( void )
{
union REGS inr,outr; /* registers */
struct SREGS sr; /* registers */
/* pass on to the original routine */
(*old_int_1c)();
/* see if UART interrupts are off - indicates request from
foreground to terminate */
if ( inportb( PIC_INTERRUPT_MASK_PORT ) & i8259bit ) {
/* unhook the timer vector */
disable();
setvect( INT1C, old_int_1c );
enable();
/* deactivate the COM driver */
com_deinstall();
/* all done */
inr.h.ah = INT21_FREE_MEM;
sr.es = _psp;
int86x( INT21, &inr, &outr, &sr );
}
/* shuffle stuff between the available buffers (do the real work!) */
/* transfer any characters from the incoming serial buffer
to tfpcx unless -R receive-only */
if ( ! rflag )
while ( ! com_rx_empty() )
tfpcx_writech( (u_char)com_rx() );
/* transfer what we can from tfpcx to the serial buffer */
while ( com_tx_ready() && tfpcx_request() )
com_tx( (int)tfpcx_readch() );
}
/*-----------------------------------------------------------------------*/
/*
* see if COM interrupts already in use - probably indicates either
* this TSR already loaded, or something else is using the port. Note
* that this duplicates some definitions from ibmcom.c
*/
bool portbusy( int portnum )
{
const char i8259levels[] = { 4, 3, 4, 3 };
/* see if the 8259 bit for this port is clear (enabled) */
i8259bit = 1 << i8259levels[portnum-1];
if ( ! (inportb( PIC_INTERRUPT_MASK_PORT ) & i8259bit))
return( TRUE );
else
return( FALSE );
}
/*-----------------------------------------------------------------------*/
/*
* main program
*/
void main( int argc, char** argv )
{
union REGS inr,outr; /* registers */
struct SREGS sr; /* registers */
int com_retcode; /* retcode from com_ routine */
/* resolve the command line arguments */
if (! getopts( argc, argv )) {
printf( "\nTFLINK not installed\n" );
exit( 1 );
}
/* handle unloading of already running TSR */
if ( uflag ) {
/* see if PIC IRQ set (bit clear) for the port */
if ( ! portbusy( sio_port )) {
printf( "\nCOM%d is not busy - TFLINK not running\n",
sio_port );
exit( 1 );
}
/* set the bit - disable PIC UART interrupts - the
running TSR should spot this and drop out */
outportb( PIC_INTERRUPT_MASK_PORT,
inportb( PIC_INTERRUPT_MASK_PORT) | i8259bit );
/* job done */
if (! nflag)
printf( "\nTFLINK unloaded\n" );
exit( 0 );
}
/* not unload - confirm options to user unless -N used */
if (! nflag)
printopts();
/* check that the port is not already in use (by us?) */
if ( portbusy( sio_port )) {
printf( "\nCOM%d is busy - TFLINK may already be running\n",
sio_port );
printf( "TFLINK not installed\n" );
exit( 1 );
}
/* check for the presence of TFPCX at the expected interrupt */
if (! tfpcx_check() ) {
printf( "\nTFPCX not found at interrupt 0x%02X, exiting\n",
tfpcx_interrupt );
printf( "TFLINK not installed\n" );
exit( 1 );
}
/* print TFPCX version installed */
if (! nflag) {
printf( "\nTFPCX version %d.%d found at 0x%02X\n",
(u_int)(tfpcx_version() >> 8),
(u_int)(tfpcx_version() & 0xFF),
tfpcx_interrupt );
}
/* set up UART to requested data rate */
if ( (com_retcode=com_install( sio_port )) != 0 ) {
printf( "\ncom_install() error %d\n", com_retcode );
printf( "TFLINK not installed\n" );
exit( 1 );
}
com_raise_dtr();
com_set_speed( sio_baud );
com_set_parity( COM_NONE, 1 );
/* hook int 1C timer clock interrupt */
disable();
old_int_1c = getvect( INT1C );
setvect( INT1C, int_1c );
enable();
/* free environment space memory - not required */
inr.h.ah = INT21_FREE_MEM;
sr.es = (u_int)peek( _psp, 0x2C );
int86x( INT21, &inr, &outr, &sr );
/* install this program as a TSR */
inr.h.ah = INT21_TSR;
inr.h.al = 0x00;
inr.x.dx = TSR_MEMORY;
int86( INT21, &inr, &outr );
}